// 权限表
//
// 此处采用RBAC0模型来构建权限体系，即用户有多角色、角色又有多权限
//
// 权限又拆分为菜单、页面、按钮、接口四种权限，然后权限后面又添加权限类型来区分前台/后台的权限
// menu:xxx、page:xxx、button:xxx、api:xxx的形式来区分各个权限
//
// 超管权限：user_id=1为超级管理员权限，该用户会返回所有的权限、子用户列表
package xauth

import (
	"fmt"

	"gorm.io/gorm"
)

// 配置项
type Config struct {
	DB            *gorm.DB                    // 数据库连接
	AuthorityName string                      // 权限表
	RoleName      string                      // 角色表
	RoleAuthName  string                      // 角色权限表
	RoleUserName  string                      // 用户角色表
	UserChildName string                      // 用户关联表
	AuthMap       map[uint]string             // 权限类型字典
	ErrorFunc     func(msg string, err error) // 错误记录函数
}

// 默认配置
var _default Config = Config{
	AuthorityName: "auth",
	RoleName:      "auth_role",
	RoleAuthName:  "auth_role_auth",
	RoleUserName:  "auth_role_user",
	UserChildName: "auth_user_child",
	AuthMap:       map[uint]string{1: "默认权限"},
}

// 配置项注入
func Regedit(c *Config) {
	if c == nil {
		return
	}
	if _default.DB == nil && c.DB != nil {
		_default.DB = c.DB
	}
	if c.AuthorityName != "" {
		_default.AuthorityName = c.AuthorityName
	}
	if c.RoleName != "" {
		_default.RoleName = c.RoleName
	}
	if c.RoleUserName != "" {
		_default.RoleUserName = c.RoleUserName
	}
	if c.UserChildName != "" {
		_default.UserChildName = c.UserChildName
	}
	if c.RoleAuthName != "" {
		_default.RoleAuthName = c.RoleAuthName
	}
	if len(c.AuthMap) > 0 {
		// 如果传入了权限类型字典，则此处将字典进行替换
		_default.AuthMap = c.AuthMap
	}
	if c.ErrorFunc != nil {
		_default.ErrorFunc = c.ErrorFunc
	}
	if _default.DB != nil {
		_default.DB.
			Set("gorm:table_options", "ENGINE=MyISAM").
			AutoMigrate(&Authority{}, &Role{},
				&RoleAuth{}, &RoleUser{}, &UserChild{},
			)
	}
}

// 权限明细表
type Authority struct {
	Id        uint   `gorm:"column:id;primaryKey;type:INT UNSIGNED;not null;autoIncrement" json:"id" form:"id"`   // 权限ID
	Fid       uint   `gorm:"column:fid;type:INT UNSIGNED;comment:上级ID" json:"fid" form:"fid"`                     // 上级权限ID
	Code      string `gorm:"column:code;type:VARCHAR(200);comment:权限标识;UNIQUEINDEX:code" json:"code" form:"code"` // 权限标识，使用menu:xxx、page:xxx、button:xxx、api:xxx的形式来区分各个权限
	Title     string `gorm:"column:title;type:VARCHAR(200);comment:权限标题" json:"title" form:"title"`               // 权限标题
	Type      uint   `gorm:"column:type;type:INT UNSIGNED;comment:权限来源;UNIQUEINDEX:code" json:"type" form:"type"` // 权限来源
	UserId    uint   `gorm:"column:user_id;type:INT UNSIGNED;comment:权限创建人" json:"user_id" form:"user_id"`        // 创建人ID
	CreatedAt string `gorm:"column:created_at;type:DATETIME;comment:创建时间" json:"created_at" form:"created_at"`    // 创建时间
	UpdatedAt string `gorm:"column:updated_at;type:DATETIME;comment:最后修改时间" json:"-" form:"-"`                    // 更新时间
}

// 获取表名
func (c *Authority) TableName() string {
	return _default.AuthorityName
}

// 角色表
type Role struct {
	Id        uint   `gorm:"column:id;primaryKey;type:INT UNSIGNED;not null;autoIncrement" json:"id" form:"id"` // 角色ID
	Title     string `gorm:"column:title;type:VARCHAR(200);comment:角色标题" json:"title" form:"title"`             // 角色标题
	CreatedAt string `gorm:"column:created_at;type:DATETIME;comment:创建时间" json:"created_at" form:"created_at"`  // 创建时间
	UpdatedAt string `gorm:"column:updated_at;type:DATETIME;comment:最后修改时间" json:"-" form:"-"`                  // 更新时间
}

// 获取表名
func (c *Role) TableName() string {
	return _default.RoleName
}

// 角色权限表
type RoleAuth struct {
	Id        uint   `gorm:"column:id;primaryKey;type:INT UNSIGNED;not null;autoIncrement" json:"id" form:"id"`                 // 角色ID
	RoleId    uint   `gorm:"column:role_id;type:INT UNSIGNED;comment:角色ID;UNIQUEINDEX:role_auth" json:"role_id" form:"role_id"` // 角色ID
	AuthId    uint   `gorm:"column:auth_id;type:INT UNSIGNED;comment:权限ID;UNIQUEINDEX:role_auth" json:"auth_id" form:"auth_id"` // 权限ID
	CreatedAt string `gorm:"column:created_at;type:DATETIME;comment:创建时间" json:"created_at" form:"created_at"`                  // 创建时间
}

// 获取表名
func (c *RoleAuth) TableName() string {
	return _default.RoleAuthName
}

// 角色用户表
type RoleUser struct {
	Id        uint   `gorm:"column:id;primaryKey;type:INT UNSIGNED;not null;autoIncrement" json:"id" form:"id"`                 // 角色ID
	RoleId    uint   `gorm:"column:role_id;type:INT UNSIGNED;comment:角色ID;UNIQUEINDEX:role_user" json:"role_id" form:"role_id"` // 角色ID
	UserId    uint   `gorm:"column:user_id;type:INT UNSIGNED;comment:用户ID;UNIQUEINDEX:role_user" json:"user_id" form:"user_id"` // 用户ID
	CreatedAt string `gorm:"column:created_at;type:DATETIME;comment:创建时间" json:"created_at" form:"created_at"`                  // 创建时间
}

// 获取表名
func (c *RoleUser) TableName() string {
	return _default.RoleUserName
}

// 用户关联表
type UserChild struct {
	Id         uint   `gorm:"column:id;primaryKey;type:INT UNSIGNED;not null;autoIncrement" json:"id" form:"id"`                                // 角色ID
	SuperiorId uint   `gorm:"column:superior_id;type:INT UNSIGNED;comment:上级用户ID;UNIQUEINDEX:user_child" json:"superior_id" form:"superior_id"` // 上级用户ID
	UserId     uint   `gorm:"column:user_id;type:INT UNSIGNED;comment:用户ID;UNIQUEINDEX:user_child" json:"user_id" form:"user_id"`
	Type       uint   `gorm:"column:type;type:INT UNSIGNED;comment:权限来源;UNIQUEINDEX:user_child" json:"type" form:"type"` // 权限来源            // 用户ID
	CreatedAt  string `gorm:"column:created_at;type:DATETIME;comment:创建时间" json:"created_at" form:"created_at"`          // 创建时间
}

// 获取表名
func (c *UserChild) TableName() string {
	return _default.UserChildName
}

// 错误记录及处理函数
// 使用fmt.Errorf %w进一步封装，以便xlog/errors等进行日志记录
//
//	msg	错误提示消息
//	err	错误信息
func errFun(msg string, err error) {
	if _default.ErrorFunc != nil {
		_default.ErrorFunc(msg, fmt.Errorf("%w", err))
	}
}
